Py.Cafe

jackparmer/

open-cv example

Image Processing Dashboard with Dash & OpenCV

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import dash
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import dash_bootstrap_components as dbc
import cv2
import numpy as np
import base64
from io import BytesIO
from PIL import Image

# Initialize the Dash app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container([
    dbc.Row([
        dbc.Col(html.H1("Dash with OpenCV Example"), className="mb-4")
    ]),
    dbc.Row([
        dbc.Col(dcc.Upload(
            id='upload-image',
            children=html.Div(['Drag and Drop or ', html.A('Select a File')]),
            style={
                'width': '100%', 'height': '60px', 'lineHeight': '60px',
                'borderWidth': '1px', 'borderStyle': 'dashed', 'borderRadius': '5px',
                'textAlign': 'center', 'margin': '10px'
            },
            multiple=False
        ), width=12)
    ]),
    dbc.Row([
        dbc.Col(html.Img(id='output-image'), width=12)
    ]),
    dbc.Row([
        dbc.Col(dbc.Button("Grayscale", id='grayscale-button', color='primary', className="mt-4"), width=3),
        dbc.Col(dbc.Button("Blur", id='blur-button', color='secondary', className="mt-4"), width=3),
        dbc.Col(dbc.Button("Edge Detection", id='edge-button', color='success', className="mt-4"), width=3),
        dbc.Col(dbc.Button("Invert Colors", id='invert-button', color='danger', className="mt-4"), width=3)
    ])
], fluid=True)

def parse_contents(contents):
    content_type, content_string = contents.split(',')
    decoded = base64.b64decode(content_string)
    image = Image.open(BytesIO(decoded))
    return np.array(image)

def apply_grayscale(image):
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR)

def apply_blur(image):
    return cv2.GaussianBlur(image, (15, 15), 0)

def apply_edge_detection(image):
    edges = cv2.Canny(image, 100, 200)
    return cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)

def apply_invert(image):
    return cv2.bitwise_not(image)

@app.callback(
    Output('output-image', 'src'),
    [Input('upload-image', 'contents'),
     Input('grayscale-button', 'n_clicks'),
     Input('blur-button', 'n_clicks'),
     Input('edge-button', 'n_clicks'),
     Input('invert-button', 'n_clicks')],
    [State('upload-image', 'contents')]
)
def update_output(contents, grayscale_n, blur_n, edge_n, invert_n, state_contents):
    if contents is None:
        raise dash.exceptions.PreventUpdate

    image = parse_contents(state_contents)

    ctx = dash.callback_context

    if not ctx.triggered:
        button_id = 'None'
    else:
        button_id = ctx.triggered[0]['prop_id'].split('.')[0]

    if button_id == 'grayscale-button':
        image = apply_grayscale(image)
    elif button_id == 'blur-button':
        image = apply_blur(image)
    elif button_id == 'edge-button':
        image = apply_edge_detection(image)
    elif button_id == 'invert-button':
        image = apply_invert(image)

    _, buffer = cv2.imencode('.jpg', image)
    encoded_image = base64.b64encode(buffer).decode('utf-8')
    return f'data:image/jpeg;base64,{encoded_image}'

if __name__ == '__main__':
    app.run_server(debug=True)